#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <cstring>


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "logMessage.hpp"
#include "Util.hpp"

// 这里定制计算机协议
namespace ns_protocal
{
#define SEP "@@"
#define SEPLEN strlen(SEP)
#define HEADER_SEP "##"
#define HEADER_SEP_LEN strlen(HEADER_SEP)

    //1@@+@@1-->3##1@@+@@1##
    std::string AddHeader(const std::string &str)
    {
        std::cout << "AddHeader 之前:\n"
                  << str << std::endl;
        std::string s = std::to_string(str.size());
        s += HEADER_SEP;
        s += str;
        s += HEADER_SEP;

        std::cout << "AddHeader 之后:\n"
                  << s << std::endl;

        return s;
    }

    //根据长度提取有效载荷
    // 3##1@@+@@1##-->1@@+@@1
    std::string RemoveHeader(const std::string &str, int len)
    {
        std::cout << "RemoveHeader 之前:\n"
                  << str << std::endl;

        std::string res = str.substr(str.size() - HEADER_SEP_LEN - len, len);

        std::cout << "RemoveHeader 之后:\n"
                  << res << std::endl;
        return res;
    }


    //去网络里读：-1读取失败、0没读完、返回有效长度
    //package里存着整个字符串
    int ReadPackage(int sock, std::string &inbuffer, std::string *package)
    {
        std::cout << "ReadPackage inbuffer 之前: " << inbuffer << std::endl;

        // 边读取
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer - 1), 0);
        if (s <= 0) return -1;

        buffer[s] = 0;
        inbuffer += buffer;

        std::cout << "ReadPackage inbuffer 之中: " << inbuffer << std::endl;

        // 边分析， 3##1+1##
        int pos = inbuffer.find(HEADER_SEP);
        if (pos == std::string::npos) return 0;  
        std::string lenStr = inbuffer.substr(0, pos); 

        //拿到有效字符串的长度len
        int len = Util::toInt(lenStr);  
        //总字符串的长度                                 
        int targetPackageLen = lenStr.size() + len + 2 * HEADER_SEP_LEN; 
        
        //如果小于就不用继续了，下次继续读追加就行
        if (inbuffer.size() < targetPackageLen) return 0;          

        // 提取到了报文有效载荷，inbuffer没有动
        *package = inbuffer.substr(0, targetPackageLen);
        // 从inbuffer中直接移除整个报文
        inbuffer.erase(0, targetPackageLen);             

        std::cout << "ReadPackage inbuffer 之后: "<< inbuffer << std::endl;

        //返回有效字符串的长度len
        return len;
    }

    class Request
    {
    public:
        Request() {}
        Request(int x, int y, char op) : _x(x), _y(y), _op(op)
        {
        }

        // client: 1 + 2-->1@@+@@2
        bool Serialize(std::string *outStr)
        {
            *outStr = "";

            std::string x_string = std::to_string(_x);
            std::string y_string = std::to_string(_y);

            // 手动序列化
            // 1 + 2------>1@@+@@2
            *outStr = x_string + SEP + _op + SEP + y_string;

            std::cout << "Request Serialize:" << *outStr << std::endl;

            return true;
        }

        // server: 1@@+@@2-->1 + 2
        bool Deserialize(const std::string &inStr)
        {
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if (result.size() != 3)
                return false;
            if (result[1].size() != 1)
                return false;
            _x = Util::toInt(result[0]);
            _y = Util::toInt(result[2]);
            _op = result[1][0];
            std::cout << "Request Deserialize:" << _x << " " << _op << " " << _y << std::endl;

            return true;
        }
        ~Request() {}

    public:
        int _x;
        int _y;
        char _op;
    };

    class Response
    {
    public:
        Response() {}
        Response(int result, int code) : _result(result), _code(code)
        {
        }

        //
        bool Serialize(std::string *outStr)
        {
            *outStr = "";

            std::string res_string = std::to_string(_result);
            std::string code_string = std::to_string(_code);

            *outStr = res_string + SEP + code_string;

            std::cout << "Response Serialize:" << *outStr << std::endl;
            return true;
        }

        //
        bool Deserialize(const std::string &inStr)
        {

            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if (result.size() != 2)
                return false;

            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);

            std::cout << "Response Serialize:"
                      << "result:" << _result << "[" << _code << "]" << std::endl;

            return true;
        }

        ~Response() {}

    public:
        int _result;
        int _code; // 0 success, 1,2,3,4代表不同的错误码
    };
}